<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <script type="text/javascript" src="../public/cdn/vue/2.6.10/vue.js"></script>
        <script type="text/javascript" src="../public/cdn/vue-router/3.0.1/vue-router.min.js"></script>
    </head>

    <body>
        <div id="app">
            <h1>单页面演示vue router</h1>
            <p>当前路由：{{$route.path}}</p>
            <p><button @click="goBack">回到上一个</button></p>
            <p>
                <!--使用router-Link组件来导航（默认会被渲染成一个<a>标签）. to属性指定链接-->
                <router-link to="/foo/a">/foo/a，等同于:to="{path='/foo/a'}"</router-link><br/>
                <router-link to="/bar/test?q1=a">/bar/test?q1=a</router-link><br/>
                <!-- 若使用to的对象写法，如果携带了params，则不能使用path，而要使用name -->
                <router-link :to="{name: 'bar', params: {id: 'test'}}">通过name指定路由，通过params指定参数</router-link><br/>
                <router-link to="/parent/child">演示路由嵌套</router-link><br/>
                <router-link to="/rdr">演示重定向</router-link><br/>
            </p>
            <!-- 路由出口，匹配到的组件将渲染到这里 -->
            <router-view></router-view>
        </div>
    </body>

    <!-- 通过自定义的script标签定义组件模板 -->
    <script type="text/x-template" id="bar">
        <div>
            <p>bar</p>
            <p>$route.params={{ $route.params }}</p>
            <p>id={{ id }}</p>
            <p>q1={{ q1 }}</p>
            <p>$route.query={{ $route.query }}</p>
        </div>
    </script>
    <script>
        // 定义路由：将组件 (components) 映射到路由 (routes)；匹配的优先级就按照路由的定义顺序：路由定义得越早，优先级就越高
        var foo = {
            template: '<div>foo $route.params={{ $route.params }}</div>'
        }
        // 通过#bar指定自定义的script标签定义组件模板
        var bar = {
            template: '#bar',
            props: ['id', 'q1'],
            data() {
                return {
                    msg: 'bar'
                }
            },
            beforeRouteUpdate(to, from, next) {
                // 当目的地和当前路由相同，只是参数发生了改变时，路由不会被重新渲染，所以当路由变化时，我们可以通过监听 beforeRouteUpdate 这个钩子函数来更新视图
                console.log('beforeRouteUpdate：' + from.path + '==>' + to.path)
                next(); // 进入路由
                // next('/bar'); // 改变路由方向， 跳转到/bar
                // next(false); // 返回原来的页面，即终止导航
            },
            beforeRouteEnter(to, from, next) {
                console.log('beforeRouteEnter：' + from.path + '==>' + to.path)
                next((vm)=>{
                    console.log(vm.msg)
                }); // 仅在beforeRouteEnter中可用，vm是当前进入的组件实例
            },
            beforeRouteLeave(to, from, next) {
                console.log('beforeRouteLeave：' + from.path + '==>' + to.path)
                next();
            }
        }
        var parent = {
            template: `
            <div>
                <h2>this is parent </h2>
                <router-view></router-view>
            </div>
            `
        }
        var child = {
            template: `
            <div>
                <h2>this is child {{ $route.path }} </h2>
            </div>
            `
        }
        var router = new VueRouter({
            mode: 'hash', // 默认hash，即url后面会出现#；使用history模式，使用浏览器的history.pushState方法来实现路由，当使用history模式时，URL不会出现#，并且刷新页面不会重新加载页面
            routes: [
                { path: '/foo*/*', component: foo }, // 路径匹配引擎用的是path-to-regexp，支持*通配符，此时匹配的部分会添加到$route.params，第一个匹配的为0，第二个为1，以此类推
                {
                    path: '/bar/:id',
                    name: 'bar',
                    component: bar,
                    // props: true,  // 是否将路由参数传入组件作为props，这样子子组件可以定义props并直接使用属性，但只支持params参数，不支持query参数
                    props({query,params}) { // 方式二：使用函数，第一个参数是组件路由信息，这里通过结构写法，将params和query合并
                      return {
                          ...params,
                          ...query
                      }
                    },
                },  // 访问/bar/test?a=b时，$route.params.id为test，$route.query.a为b
                {
                    path: '/parent',
                    component: parent,
                    children: [
                        {
                            path: 'child',
                            component: child   // 嵌套路由配置，当/parent/child时匹配成功，child会被渲染到parent的<router-view>中
                        }
                    ]
                },
                { path: '/redirect', redirect: '/bar/test', alias: '/rdr' }   // 重定向不会应用在跳转路由上，即不会经过/redirect，相当于从上个路由跳转到重定向的路由上
            ]
        });
        const app = new Vue({
            el: '#app',
            router: router,
            methods: {
                goBack() {
                    // window.history.length > 1 ? this.$router.go(-1) : this.$router.push('/')
                    this.$router.back();  // 等同于this.$router.go(-1);
                }
            },
            watch: {
                $route(to, from) {
                    // 对路由变化做出响应
                    console.log('路由变化了:' + from.path + '==>' + to.path)
                }
            }
        });
        // 编程式导航，push会向history添加新的路由，replace不会添加到history中
        router.push('/foo/a/b/c');
    </script>

</html>
